package com.todo.strategy.online.application.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.todo.common.common.enums.BizErrorCodeEnum;
import com.todo.common.common.exception.BizException;
import com.todo.common.utils.StringUtils;
import com.todo.component.redis.RedisService;
import com.todo.strategy.common.constant.StrategyOnlineKeyBuild;
import com.todo.strategy.online.application.convert.StrategyConvert;
import com.todo.strategy.online.application.entity.bo.PlanContentBO;
import com.todo.strategy.online.application.service.PlanContentService;
import com.todo.strategy.online.infrastructure.entity.po.PlanContentPO;
import com.todo.strategy.online.infrastructure.repository.PlanContentRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * (PlanContent)表服务实现类
 *
 * @author zhangwenxiang
 * @since 2024-03-04 00:19:47
 */
@Slf4j
@Service("planContentService")
public class PlanContentServiceImpl implements PlanContentService {

    @Resource
    private PlanContentRepository planContentRepository;
    @Resource
    private RedisService redisService;

    @Override
    public Boolean insertPlanContent(PlanContentBO planContentBO) {
        if (planContentBO == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        if (!planContentBO.baseCheck()) {
            log.error("PlanContentService#insertPlanContent 新增计划内容失败，基础校验失败 planContentBO：【{}】", JSONObject.toJSONString(planContentBO));
            return false;
        }
        PlanContentBO alreadyData = queryPlanContentByRelationId(planContentBO.getUserId(), planContentBO.getPlanId(), planContentBO.getPlanRelationId());
        if (alreadyData != null) {
            log.warn("PlanContentService#insertPlanContent 新增计划内容失败,已经存在对应用户关联数据  planContentBO：【{}】", JSONObject.toJSONString(planContentBO));
            throw new BizException(BizErrorCodeEnum.SUCCESS_EXIST);
        }
        PlanContentPO planContentPO = StrategyConvert.convertToPlanContentPO(planContentBO);
        Boolean insertResult = planContentRepository.insertPlanContentPO(planContentPO);
        if (insertResult) {
            String contentRelationKey = StrategyOnlineKeyBuild.strategyPlanContentRelationKey(planContentBO.getUserId(), planContentBO.getPlanId());
            redisService.hSet(contentRelationKey, String.valueOf(planContentBO.getPlanRelationId()), JSONObject.toJSONString(planContentBO));
        }
        log.info("PlanContentService#insertPlanContent 新增计划内容完成，planContentBO:【{}】结果：【{}】", JSONObject.toJSONString(planContentBO), insertResult);
        return insertResult;
    }

    @Override
    public Boolean updatePlanContent(PlanContentBO planContentBO) {
        if (planContentBO == null || planContentBO.getId() == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        PlanContentBO alreadyData = queryPlanContentById(planContentBO.getId());
        if (alreadyData == null) {
            log.error("PlanContentService#updatePlanContent 更新计划内容失败，当前主键下数据不存在 planContentBO：【{}】", JSONObject.toJSONString(planContentBO));
            throw new BizException(BizErrorCodeEnum.DATA_NOT_EXIST);
        }
        if (!alreadyData.getPlanRelationId().equals(planContentBO.getPlanRelationId())
                || !alreadyData.getUserId().equals(planContentBO.getUserId())
                || !alreadyData.getPlanId().equals(planContentBO.getPlanId())) {
            log.error("PlanContentService#updatePlanContent 更新计划内容失败，无法修改核心变更数据 planContentBO：【{}】", JSONObject.toJSONString(planContentBO));
            throw new BizException(BizErrorCodeEnum.ILLEGAL_OPERATION, "无法修改核心变更数据");
        }

        PlanContentPO planContentPO = StrategyConvert.convertToPlanContentPO(planContentBO);
        Boolean updateResult = planContentRepository.updatePlanContentPOById(planContentPO);
        if (updateResult) {
            String contentRelationKey = StrategyOnlineKeyBuild.strategyPlanContentRelationKey(planContentBO.getUserId(), planContentBO.getPlanId());
            redisService.hSet(contentRelationKey, String.valueOf(planContentBO.getPlanRelationId()), JSONObject.toJSONString(planContentBO));
        }
        log.info("PlanContentService#updatePlanContent 更新计划内容完成，planContentBO:【{}】结果：【{}】", JSONObject.toJSONString(planContentBO), updateResult);
        return updateResult;
    }

    @Override
    public Boolean removePlanContentById(Long id) {
        if (id == null || id < 0) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        PlanContentBO planContentBO = queryPlanContentById(id);
        if (planContentBO == null) {
            return true;
        }
        Boolean remove = planContentRepository.removePlanContentPOById(id);
        if (remove) {
            String contentRelationKey = StrategyOnlineKeyBuild.strategyPlanContentRelationKey(planContentBO.getUserId(), planContentBO.getPlanId());
            redisService.hDel(contentRelationKey, String.valueOf(planContentBO.getPlanRelationId()));
        }
        log.info("PlanContentService#removePlanContentById 根据主键删除计划清单内容完成，id:【{}】清除数量：【{}】", id, remove);
        return remove;
    }

    @Override
    public Boolean removePlanContentByPlanId(Long userId, Long planId) {
        if (planId == null || planId < 0) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        Long removeCount = planContentRepository.removePlanContentPOByPlanId(userId, planId);
        if (removeCount > 0) {
            redisService.del(StrategyOnlineKeyBuild.strategyPlanContentRelationKey(userId, planId));
        }
        log.info("PlanContentService#removePlanContentByPlanId 根据关联id删除计划清单内容完成，清除数量：【{}】", removeCount);
        return true;
    }

    @Override
    public PlanContentBO queryPlanContentById(Long id) {
        if (id == null || id < 0) {
            return null;
        }
        PlanContentPO planContentPO = planContentRepository.queryPlanContentPOById(id);
        return StrategyConvert.convertToPlanContentBO(planContentPO);
    }

    @Override
    public PlanContentBO queryPlanContentByRelationId(Long userId, Long planId, Long relationId) {
        if (userId == null || userId < 0 || relationId == null || relationId < 0) {
            return null;
        }
        String contentRelationKey = StrategyOnlineKeyBuild.strategyPlanContentRelationKey(userId, planId);
        String cacheData = redisService.hGet(contentRelationKey, String.valueOf(relationId));
        if (StringUtils.isNotBlank(cacheData)) {
            PlanContentBO planContentBO = JSONObject.parseObject(cacheData, PlanContentBO.class);
            log.info("PlanContentService#queryPlanContentByRelationId 缓存根据关联id查询计划清单内容命中缓存，relationId：【{}】planContentBO:【{}】", relationId, JSONObject.toJSONString(planContentBO));
            return planContentBO;
        }
        PlanContentPO planContentPO = planContentRepository.queryPlanContentPOByPlanRelationId(userId, relationId);
        PlanContentBO planContentBO = StrategyConvert.convertToPlanContentBO(planContentPO);
        redisService.hSet(contentRelationKey, String.valueOf(relationId), JSONObject.toJSONString(planContentBO));
        log.info("PlanContentService#queryPlanContentByRelationId 数据库根据关联id查询计划清单内容完成，relationId：【{}】planContentBO:【{}】", relationId, JSONObject.toJSONString(planContentBO));
        return planContentBO;
    }

    @Override
    public List<PlanContentBO> queryPlanContentByPlanId(Long userId, Long planId) {
        if (userId == null || userId < 0 || planId == null || planId < 0) {
            return Collections.emptyList();
        }
        String contentRelationKey = StrategyOnlineKeyBuild.strategyPlanContentRelationKey(userId, planId);
        List<PlanContentBO> result = new ArrayList<>();
        if (redisService.hasKey(contentRelationKey)) {
            Map<String, String> cacheMap = redisService.hGetAll(contentRelationKey);
            for (String data : cacheMap.keySet()) {
                PlanContentBO planContentBO = JSONObject.parseObject(cacheMap.get(data), PlanContentBO.class);
                if (planContentBO != null) {
                    result.add(planContentBO);
                }
            }
            log.info("PlanContentService#queryPlanContentByPlanId 缓存根据用户和计划清单id查询计划清单内容列表完成 userId:【{}】,planId:【{}】，结果idList：【{}】", userId, planId, JSONObject.toJSONString(cacheMap.keySet()));
            return result;
        }
        List<PlanContentPO> planContentPOList = planContentRepository.queryPlanContentPOByPlanId(userId, planId);
        if (CollectionUtils.isEmpty(planContentPOList)) {
            log.info("PlanContentService#queryPlanContentByPlanId 根据用户和计划清单id查询计划清单内容列表完成,数据为空 userId:【{}】,planId:【{}】", userId, planId);
            return Collections.emptyList();
        }
        List<PlanContentBO> collect = planContentPOList.stream().map(StrategyConvert::convertToPlanContentBO).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(collect)) {
            collect.forEach(item -> {
                redisService.hSet(contentRelationKey, String.valueOf(item.getPlanRelationId()), JSONObject.toJSONString(collect));
            });

        }
        return collect;
    }
}
